package th.go.drr.gps.dao;

import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Example;

import th.go.drr.gps.common.InfrastructureException;
import th.go.drr.gps.dao.h.JpaHandler;
import th.go.drr.gps.persistance.HibernateUtil;



public class JpaTemplate<T> implements JpaHandler<T> {

	private static Logger logger = Logger.getLogger(JpaTemplate.class);

	public JpaTemplate() {
		// HibernateUtil.beginTransaction();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> findAll(Class<T> clazz) {
		List<T> l = null;
		try {
			l = HibernateUtil.getSession().createCriteria(clazz).list();
		} catch (HibernateException e) {
			logger.info(e.getMessage(), e);
			throw new InfrastructureException(e);
		}
		return l;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> find(T o, int first, int max) {
		List<T> l = null;
		try {
			Criteria cri = HibernateUtil.getSession().createCriteria(
					o.getClass());
			cri.setMaxResults(max);
			cri.setFirstResult(first);
			l = cri.add(Example.create(o)).list();
		} catch (HibernateException e) {
			logger.info(e.getMessage(), e);
			throw new InfrastructureException(e);
		}
		return l;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T findById(Class<T> clazz, Long id) {
		Session session = HibernateUtil.getSession();
		T o = null;
		try {
			o = (T) session.load(clazz, id);
		} catch (HibernateException e) {
			logger.info(e.getMessage(), e);
			throw new InfrastructureException(e);
		}
		return o;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public T findById(Class<T> clazz, Integer id) {
		Session session = HibernateUtil.getSession();
		T o = null;
		try {
			o = (T) session.load(clazz, id);
		} catch (HibernateException e) {
			logger.info(e.getMessage(), e);
			throw new InfrastructureException(e);
		}
		return o;
	}

	@Override
	public Long insert(T o) {
		long id = -1L;
		Transaction tx = null;
		try {
			tx = HibernateUtil.getSession().beginTransaction();
			id = (Long) HibernateUtil.getSession().save(o);
			tx.commit();
		} catch (HibernateException e) {
			logger.info(e.getMessage(), e);
			tx.rollback();
			throw new InfrastructureException(e);
		}
		return id;
	}

	@Override
	public void update(T o) {
		Transaction tx = null;
		try {
			tx = HibernateUtil.getSession().beginTransaction();
			HibernateUtil.getSession().update(o);
			tx.commit();
		} catch (HibernateException e) {
			logger.info(e.getMessage(), e);
			tx.rollback();
			throw new InfrastructureException(e);
		}
	}

	@Override
	public void delete(T o) {
		try {
			HibernateUtil.getSession().delete(o);
		} catch (HibernateException e) {
			logger.info(e.getMessage(), e);
			throw new InfrastructureException(e);
		}
	}
}